#!/bin/bash

#/*******************************************************************
# * This file is part of the Emulex Linux Device Driver for         *
# * Fibre Channel Host Bus Adapters.                                *
# * Copyright (C) 2003-2006 Emulex.  All rights reserved.           *
# * EMULEX and SLI are trademarks of Emulex.                        *
# * www.emulex.com                                                  *
# *                                                                 *
# * This program is free software; you can redistribute it and/or   *
# * modify it under the terms of version 2 of the GNU General       *
# * Public License as published by the Free Software Foundation.    *
# * This program is distributed in the hope that it will be useful. *
# * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
# * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
# * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
# * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
# * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
# * more details, a copy of which can be found in the file COPYING  *
# * included with this package.                                     *
# *******************************************************************/
######################################################################
#
# install script for Emulex Linux Fibre Channel Driver RPMs
#
INSTALLER_VERSION='$Id: ioctl-install 3028 2006-08-29 21:39:23Z sf_support $'
INSTALLER_VERSION=`echo ${INSTALLER_VERSION} | perl -pe '/\s+([\d\.]*)\s+/;$_="$1\n"'`

# Exit codes:
#   0   Success.
#   1   Unable to determine distribution type.
#   2   Unknown error.
#   5   Invalid command line parameter.
#  10   Failure uninstalling Application Helper Module.
#  12   Other package(s) depend(s) upon packages to be removed.
#  15   One or more Emulex Linux LPFC packages already installed.
#  17   One or more conflicting packages are installed.
#  20   Success, system requires reboot to complete installation.
#  25   Success, system requires reboot to complete uninstallation.
#  52   Error installing lpfc_2.6_ioctl_module RPM.
#  54   Error loading lpfcdfc module.
#  60   Kernel source is not installed, RPM installation cannot continue.
#  70   Compilers are not installed, RPM installation cannot continue.
#  75   Neither kernel source nor compilers are installed, RPM installation
#        cannot continue.
#  90   Error installing init script.
#  95   Error copying elxlpfc init script to ${INITSCRIPT_DESTINATION}.
#  97   Error installing elxlpfc init script.
# 100   Incorrect version of lpfc.ko installed for this kernel.
# 101   Multiple versions of lpfc.ko installed for this kernel.
# 102   No lpfc.ko module installed for this kernel.
# 103   Incorrect version of lpfc.ko module installed for this kernel.
# 104   An incorrect version of an Application Helper Module RPM is installed.
# 105   Error returned by 'find' when searching for lpfcdfc.ko in /lib/modules.
# 106   An Application Helper Module installation needs to be repaired.
# 107   Multiple instances of lpfcdfc.ko exist in /lib/modules/$(uname -r).
# 125   Unable to back up old Emulex Application Helper Module.
# 127   Unable to unload old Emulex Application Helper Module.
# 130   Error backing up /etc/modprobe.conf.
# 140   Error updating /etc/modprobe.conf.
# 150   Error parsing awk output when unloading Application Helper Module.
# 255   Error determining script command.

DRIVER_NAME=lpfc
DFCDRIVER_NAME=lpfcdfc
LPFCRPM_BASENAME=${DRIVER_NAME}driver_2.6
DFCRPM_BASENAME=lpfc_2.6_ioctl_module
DFCRPM_DKMS_BASENAME=lpfc_2.6_ioctl_module_dkms
CONFLICTING_RPM_BASENAMES="lpfc_2.6_ioctl_module_dkms"
INITSCRIPT_NAME=elxlpfc
LPFCDRIVER_VERSION=8.1.6.6
DFCDRIVER_VERSION=2.1.6
DFCDRIVER_DESCRIPTION="LPFC DFC Application Helper Module source RPM"
DFC_RPM_RELEASE=1
DFCDRIVER_DIR="/usr/src/lpfcdfc"
SAVEDFILESDIR="${DFCDRIVER_DIR}/savedfiles"

DRIVER_DIR=.
LOGFILE="/usr/src/lpfcdfc/utils-install.log"

GENERIC_MESSAGE="Please contact Emulex Technical Support"
HELP_MESSAGE="Please execute '$0 --help' for usage information."

let NEED_SOURCE_PACKAGE=0
let NEED_GCC_PACKAGE=0
let DRIVER_INSTALLED=0

# Function:  log_message()
#
# Description:
#   Print the strings passed as parameters to both STDOUT as well as
#   to a log file.
#
# Parameters:
#   A series of strings.
#
# Returns:
#   0 on success.
log_message()
{
    local ECHO_OPTIONS
    LOGDIRECTORY=${LOGFILE%/*}
    if [ ! -d ${LOGDIRECTORY} ] ; then
	mkdir -p ${LOGDIRECTORY}
    fi

    if [ $# -eq 0 ] ; then
	echo "" | tee -a ${LOGFILE}
    elif [ -z "$1" ] ; then
	echo "" | tee -a ${LOGFILE}
    elif [ "$1" = "-init" ] ; then
	echo "$0 - $(date)" >> ${LOGFILE}
    else
	while [ -n "$1" ] ; do
	    if [ "${1:0:1}" = "-" ] ; then
		ECHO_OPTIONS="${1}"
	    else
		echo ${ECHO_OPTIONS} "$1" | tee -a ${LOGFILE}
	    fi
	    shift
	done
    fi

    return 0
}

exec_command()
{
    local TEMPFILE
    let RETURNVALUE=0
    
    if [ "$2" = background ] ; then
	TEMPFILE=`mktemp /tmp/elx-lpfc-install.XXXXXX`
	(eval $1 ; echo "RETURNVALUE=$?" >> ${TEMPFILE}) &
	while [ -e ${TEMPFILE} ] && [ ! -s ${TEMPFILE} ] ; do
	    sleep 3
	    log_message -en "."
	done
	. ${TEMPFILE}
	rm -f ${TEMPFILE}
    else
	eval "$1"
	RETURNVALUE=$?
    fi
    log_message -en "\n"
    return ${RETURNVALUE}
}

get_distribution ()
{
    if [ -f /etc/redhat-release ]
    then
        # this is a Red Hat install
	DISTRIBUTION=redhat
	MAKEDISTRO=RHEL
        RH_VERSION=$(rpm -qf /etc/redhat-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        ARCH=$(uname -m | sed "s/i686/i386/")
	KERNEL=$(rpm -qf /lib/modules/$(uname -r) --qf "%{VERSION}_%{RELEASE}\n")
	KERNEL_VERSION=$(rpm -qf /lib/modules/$(uname -r) --qf "%{VERSION}\n")
	KERNEL_RELEASE=$(rpm -qf /lib/modules/$(uname -r) --qf "%{RELEASE}\n")
	UNAME=$(uname -r)
        RELEASE=rhel${RH_VERSION}_${KERNEL}
        DFCDRIVER_RPM=${DFCRPM_BASENAME}-${DFCDRIVER_VERSION}-${DFC_RPM_RELEASE}.noarch.rpm
	INITSCRIPT_SOURCE=${DRIVER_DIR}/${INITSCRIPT_NAME}
	INITSCRIPT_DESTINATION=/etc/rc.d/init.d/${INITSCRIPT_NAME}
	MINIMUM_KERNEL_VERSION="2.6.9"
	MINIMUM_KERNEL_RELEASE="6.37.EL"
	MODPROBE_CONF_BACKUP=/etc/modprobe.elx
	MODPROBE_CONF_TEMP=/etc/modprobe.conf.elxinstall
	MODPROBE_CONF_TEMP2=/etc/modprobe.conf.elxinstall2
	MODPROBE_CONF=/etc/modprobe.conf
	MESSAGESFILE="/var/log/messages"
	if [ ${ARCH} = "ia64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/efi/efi/redhat/vmlinuz-${UNAME}"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	fi
	return 0
    elif [ -f /etc/SuSE-release ]; then
        # this is a Suse install
	DISTRIBUTION=suse
	MAKEDISTRO=SLES
        SUSE_VERSION=$(rpm -qf /etc/SuSE-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        ARCH=$(uname -m | sed "s/i686/i386/")
	KERNEL=$(rpm -qf /lib/modules/$(uname -r) --qf "%{VERSION}_%{RELEASE}\n")
	KERNEL_VERSION=$(rpm -qf /lib/modules/$(uname -r) --qf "%{VERSION}\n")
	KERNEL_RELEASE=$(rpm -qf /lib/modules/$(uname -r) --qf "%{RELEASE}\n")
	UNAME=$(uname -r)
        RELEASE=sles${SUSE_VERSION}_${KERNEL}
        DFCDRIVER_RPM=${DFCRPM_BASENAME}-${DFCDRIVER_VERSION}-${DFC_RPM_RELEASE}.noarch.rpm
	INITSCRIPT_SOURCE=${DRIVER_DIR}/${INITSCRIPT_NAME}
	INITSCRIPT_DESTINATION=/etc/rc.d/${INITSCRIPT_NAME}
	MINIMUM_KERNEL_VERSION="2.6.5"
	MINIMUM_KERNEL_RELEASE="7.166"
	MODPROBE_CONF_BACKUP=/etc/modprobe.conf.local.elx
	MODPROBE_CONF_TEMP=/etc/modprobe.conf.local.elxinstall
	MODPROBE_CONF_TEMP2=/etc/modprobe.conf.local.elxinstall2
	MODPROBE_CONF=/etc/modprobe.conf.local
	MESSAGESFILE="/var/log/messages /var/log/warn"
	if [ ${ARCH} = "ppc64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/vmlinux"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	fi
	return 0
    else
        log_message ""
        log_message "Unable to determine distribution type"
        return 1
    fi
}

# Function:  check_for_driver_kit()
#
# Description:
#   Verifies that a version of the Emulex Linux LPFC Application Helper
#   Module kit is not already installed.
#
# Parameters:
#   none.
#
# Returns:
#   0 - install the Application Helper Module RPM.
#   1 - A valid lpfcdfc.ko module exists in /lib/modules/${UNAME}.
#   2 - A valid lpfc.ko module does not exist in /lib/modules/${UNAME}.
#   3 - Multiple lpfc.ko modules exist in /lib/modules/${UNAME}.
#   4 - An lpfc.ko module other than ${LPFCDRIVER_VERSION} exists in /lib/modules.
#   5 - The ${INSTALLEDPACKAGE} version ${INSTALLEDVERSION} needs to be removed.
#   6 - Error attempting to find lpfcdfc.ko in /lib/modules/${UNAME}.
#   7 - LPFC DFC driver installation needs to be repaired.
#   8 - Multiple lpfcdfc.ko modules exist in /lib/modules/${UNAME}.
check_for_driver_kit()
{
    local retval
    local message
    local index
    let message=0
    let retval=0

    # Does lpfc.ko exist in /lib/modules/$(uname -r)?
    COMMAND="find /lib/modules/${UNAME} -name ${DRIVER_NAME}.ko -type f"
    LPFC_MODULEPATH=$(${COMMAND})
    if [ $? -ne 0 ] ; then
	# Error attempting to find lpfc.ko in /lib/modules/$(uname -r).
	log_message "Error attempting to find ${DRIVER_NAME}.ko in /lib/modules/${UNAME}."
	return 2
    elif [ $(${COMMAND} | wc -l) -eq 0 ] ; then
        # No:  return 2, no LPFC driver installed for this kernel.
	return 2
    elif [ $(${COMMAND} | wc -l) -ne 1 ] ; then
	# Multiple lpfc.ko modules exist in the module path.
	return 3
    fi

    # Is lpfc.ko the correct version?
    LPFC_MODULE_STRING="Emulex LightPulse Fibre Channel SCSI driver"
    LPFC_MODULEVERSION=$(strings ${LPFC_MODULEPATH} | grep --max-count=1 -e "^${LPFC_MODULE_STRING}" | sed "s/^${LPFC_MODULE_STRING} \(.*\)/\1/")
    if [ ${LPFC_MODULEVERSION} != ${LPFCDRIVER_VERSION} ] ; then
        # Return 4, ask user to install ${LPFCDRIVER_VERSION}.
	return 4
    fi

    # Yes:  Is lpfc_2.6_ioctl_module or lpfc_2.6_ioctl_module_dkms installed?
    rpm -q ${DFCRPM_BASENAME} 2>/dev/null 1>/dev/null
    if [ $? -eq 0 ] ; then
	INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${DFCRPM_BASENAME} 2>/dev/null)
	if [ $? -ne 0 ] ; then
	    log_message "FATAL ERROR - cannot get version of ${DFCRPM_BASENAME}."
	    exit 255
	fi
	INSTALLEDPACKAGE=${DFCRPM_BASENAME}
    else
	rpm -q ${DFCRPM_DKMS_BASENAME} 2>/dev/null 1>/dev/null
	if [ $? -ne 0 ] ; then
            # No:  Indicate that no package has been installed.
	    INSTALLEDPACKAGE=none
	else
	    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${DFCRPM_DKMS_BASENAME} 2>/dev/null)
	    if [ $? -ne 0 ] ; then
		log_message "FATAL ERROR - cannot get version of ${DFCRPM_DKMS_BASENAME}."
		exit 255
	    fi
	    INSTALLEDPACKAGE=${DFCRPM_DKMS_BASENAME}
	fi
    fi

    if [ ${INSTALLEDPACKAGE} != "none" ] ; then
        # Do the RPM version and release numbers match what we want?
	if [ ${INSTALLEDVERSION} != ${DFCDRIVER_VERSION} ] ; then
            # Return 5, warn user that the ioctl RPM needs to be removed.
	    return 5
	fi

        # Does lpfcdfc.ko exist in /lib/modules/${UNAME}?
	COMMAND="find /lib/modules/${UNAME} -name ${DFCDRIVER_NAME}.ko -type f"
	LPFCDFC_MODULEPATH=$(${COMMAND})
	if [ $? -ne 0 ] ; then
	    # Error attempting to find lpfcdfc.ko in /lib/modules/$(uname -r).
	    log_message "Error attempting to find ${DFCDRIVER_NAME}.ko in /lib/modules/${UNAME}."
	    return 6
	elif [ $(${COMMAND} | wc -l) -eq 0 ] ; then
	    if [ ${INSTALLEDPACKAGE} == "none" ] ; then
                # return 0, no LPFC DFC driver installed for this kernel.
		return 0
	    else
	        # return 7, LPFC DFC driver installation needs to be repaired.
		return 7
	    fi
	elif [ $(${COMMAND} | wc -l) -ne 1 ] ; then
	    # Multiple lpfcdfc.ko modules exist in the module path.
	    return 8
	fi

        # Does the 'version' string of lpfcdfc.ko in /lib/modules/$(uname -r) match?
	LPFCDFC_MODULE_STRING="Emulex LightPulse FC SCSI IOCTL"
	LPFCDFC_MODULEVERSION=$(strings ${LPFCDFC_MODULEPATH} | grep -e "^${LPFCDFC_MODULE_STRING}" | sed "s/^${LPFCDFC_MODULE_STRING} \(.*\)/\1/")
	if [ "${LPFCDFC_MODULEVERSION}" != "${DFCDRIVER_VERSION}" ] ; then
            # Return 7, LPFC DFC driver installation needs to be repaired.
	    return 7
	fi

        # Yes:  return 1, nothing needs to be done.
	return 1
    fi

    # Make with the installation.
    return 0
}

# Function:  backup_file_to_savedfiles()
#
# Description:
#   Move each file passed as a parameter to the directory specified by
#   the SAVEDFILESDIR shell variable, preserving the original path
#   information under the SAVEDFILESDIR directory.
#
# Parameters:
#   A list of filenames to save.
#
# Returns a bit pattern with the following values:
#   0 on success.
#   1 if the ${SAVEDFILESDIR} does not exist and cannot be created.
#   2 if one or more files could not be saved to ${SAVEDFILESDIR}.
#   4 if one or more original files could not be removed after they were saved.
backup_file_to_savedfiles()
{
    local i
    local RETURNVALUE
    let RETURNVALUE=0

    if [ ! -d ${SAVEDFILESDIR} ] ; then
	mkdir -p ${SAVEDFILESDIR}
	if [ $? -ne 0 ] ; then
	    log_message "Error creating ${SAVEDFILESDIR}!"
	    return 1
	fi
    fi

    for i in $@ ; do
	cp --parents $i ${SAVEDFILESDIR}
	if [ $? -ne 0 ] ; then
	    log_message "Error copying $i to a safe location!"
	    let RETURNVALUE=$((${RETURNVALUE} | 2))
	fi
	rm -f $i
	if [ $? -ne 0 ] ; then
	    log_message "Error removing $i after backup!"
	    let RETURNVALUE=$((${RETURNVALUE} | 4))
	fi
    done

    return ${RETURNVALUE}
}

# Function:  restore_files_from_savedfiles()
#
# Description:
#   Move each file passed as a parameter back to its original
#   location.
#
# Parameters:
#   A list of filenames to restore.
#
# Returns a bit pattern with the following values:
#   0 on success.
#   1 if no files are available to restore.
#   2 if one or more files could not be restored.
#   4 if one or more backup files could not be removed after they were restored.
restore_files_from_savedfiles()
{
    local DIRECTORY
    local BACKUPFILE
    local RETURNVALUE
    let RETURNVALUE=0

    # Return immediately if no files are available to be restored.
    if [ ! -d "${SAVEDFILESDIR}/$1" ] ; then
	if [ -d ${SAVEDFILESDIR} ] ; then
	    rmdir --ignore-fail-on-non-empty -p ${SAVEDFILESDIR}
	fi
	return 1
    fi

    for i in `find ${SAVEDFILESDIR}/$1 -regex "$2"` ; do
	log_message -en "\n"
	BACKUPFILE=$(echo $i | sed "s|^${SAVEDFILESDIR}/||")
	DIRECTORY=$(echo ${BACKUPFILE} | sed "s/\(.*\/\)[^\/]*/\1/")
	pushd ${SAVEDFILESDIR} 2>/dev/null 1>/dev/null
	cp --parents ${BACKUPFILE} /
	if [ $? -ne 0 ] ; then
	    log_message "Error restoring /${BACKUPFILE}!"
	    let RETURNVALUE=$((${RETURNVALUE} | 2))
	fi
	rm -f ${BACKUPFILE}
	if [ $? -ne 0 ] ; then
	    log_message "Error removing backup file ${SAVEDFILESDIR}/${BACKUPFILE}"
	    let RETURNVALUE=$((${RETURNVALUE} | 4))
	fi
	popd 2>/dev/null 1>/dev/null
	rmdir --ignore-fail-on-non-empty -p ${SAVEDFILESDIR}/${DIRECTORY}
    done

    return ${RETURNVALUE}
}

# Function:  unload_old_drivers()
#
# Description:
#   Unload any old lpfcdfc driver that may be loaded.
#
# Parameters:
#   none.
#
# Returns a bit pattern with the following values:
#   0 - all old drivers unloaded, or no old drivers were loaded.
#   1 - an error occurred while unloading one or more drivers.
#   2 - old driver is being used and cannot be unloaded.
#   4 - old driver is being referenced by another module and cannot be unloaded.
unload_old_drivers()
{
    local drivers
    local retval
    let retval=0

    log_message "Checking for old Emulex Application Helper Module ..."
    drivers=(${DFCDRIVER_NAME})
    for i in ${drivers[@]} ; do
	unload_driver ${i}
	case "$?" in
	    0) log_message "Module '${i}' successfully unloaded." ;;
	    1) log_message "An error occurred while unloading ${i}."
		let retval=$((${retval} | 1)) ;;
	    2) log_message "The ${i} driver is being used and cannot be unloaded."
		let retval=$((${retval} | 2)) ;;
	    3) log_message "The ${i} driver is being referenced by other"
		log_message "modules and cannot be unloaded."
		let retval=$((${retval} | 4)) ;;
	    4) ;;
	    *) log_message "An unknown error occurred while unloading ${i}."
		let retval=$((${retval} | 1)) ;;
	esac
    done

    return ${retval}
}

# Function:  backup_old_driver()
#
# Description:
#   Move any old drivers from the /lib/modules/${UNAME} directory to a
#   location where they will not be referenced by 'depmod -a', but
#   where they will be available if they need to be restored by the
#   '--uninstall' option to the install script.
#
# Parameters:
#   none.
#
# Returns:
#   0 on success.
backup_old_driver()
{
    # Move old copies of the Application Helper Module out of the way.
    backup_file_to_savedfiles `find /lib/modules/${UNAME}/kernel/drivers/ -regex '.*lpfcdfc\.ko'`
    if [ $? -ne 0 ] ; then
	log_message "Unable to backup old drivers."
	exit 125
    fi

    return 0
}

# Function:  restore_old_driver()
#
# Description:
#   Move any old drivers saved by the backup_old_driver() function to
#   their original locations.
#
# Parameters:
#   none.
#
# Returns:
#   0 on success.
#   nonzero on failure.
restore_old_driver()
{
    local RETURNVALUE

    log_message "Looking for old Emulex Application Helper Modules to restore..."
    restore_files_from_savedfiles "lib/modules/${UNAME}/kernel/drivers/" '.*lpfcdfc\.ko'
    let RETURNVALUE=$?

    # This function might be called even if no old drivers are
    # available to be restored, so don't fail if the search for files
    # to restore fails.
    case "${RETURNVALUE}" in
	0)  let RETURNVALUE=0 ;
	    log_message "Old Emulex Application Helper Module has been restored."
	    ;;
        1)  let RETURNVALUE=0 ;;
	*)  let RETURNVALUE=${RETURNVALUE} ;;
    esac
    return ${RETURNVALUE}
}

# Function:  backup_modprobe_conf()
#
# Description:
#   Copy the file /etc/modprobe.conf to the file specified by the the
#   first positional parameter, failing with exit code 130 if the copy
#   fails.
#
# Parameters:
#   File to which /etc/modprobe.conf should be copied.
#
# Returns:
#   0 on success,
#   exit code 130 on failure.
backup_modprobe_conf()
{
    # Make a working copy of /etc/modprobe.conf.
    cp -f ${MODPROBE_CONF} $1
    if [ $? -ne 0 ] ; then
	log_message ""
	log_message "Error backup up ${MODPROBE_CONF}"
	log_message "${GENERIC_MESSAGE}"
	exit 130
    fi

    return 0
}

# Function:  configure_modprobe_conf()
#
# Description:
#   Add /etc/modprobe.conf "install" line for the lpfcdfc module.
#
# Parameters:
#   A list of driver modules.
#
# Returns a bit pattern with the following values:
#  0 if the /etc/modprobe.conf file is not modified,
#  2 if the /etc/modprobe.conf file is modified with changes that do not require the initrd to be rebuilt.
configure_modprobe_conf()
{
    local RETURN_VALUE
    let RETURN_VALUE=0

    log_message "Configuring ${MODPROBE_CONF} ..."
    backup_modprobe_conf ${MODPROBE_CONF_TEMP}

    # Add the "install" line to the /etc/modprobe.conf file.
    let INSTALL_REF=$(grep -c -e "^[[:space:]]*install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]\+/sbin/modprobe[[:space:]]\+${DRIVER_NAME}[[:space:]]\+\&\&[[:space:]]\+/sbin/modprobe[[:space:]]\+--ignore-install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]*\$" ${MODPROBE_CONF})
    if [ ${INSTALL_REF} -eq 0 ] ; then
	echo "install ${DFCDRIVER_NAME} /sbin/modprobe ${DRIVER_NAME} && /sbin/modprobe --ignore-install ${DFCDRIVER_NAME}" >>  ${MODPROBE_CONF_TEMP}
	let RETURN_VALUE=$((${RETURN_VALUE}|2))
    fi

    # Back up and then update /etc/modprobe.conf if changes are
    # necessary.
    if [ ${RETURN_VALUE} -ne 0 ] ; then
	# Save one pre-existing backup.
	if [ -e ${MODPROBE_CONF_BACKUP} ] ; then
	    mv -f ${MODPROBE_CONF_BACKUP} ${MODPROBE_CONF_BACKUP}.old
	fi

	# Backup up /etc/modprobe.conf.
    cp -f ${MODPROBE_CONF} ${MODPROBE_CONF_BACKUP}
	if [ $? -ne 0 ] ; then
	    log_message ""
	    log_message "Error backing up ${MODPROBE_CONF}"
	    log_message "${GENERIC_MESSAGE}"
	    exit 130
	fi
	log_message "Original saved as ${MODPROBE_CONF_BACKUP}"

	# Update /etc/modprobe.conf with the changes.
	mv -f ${MODPROBE_CONF_TEMP} ${MODPROBE_CONF}
	if [ $? -ne 0 ] ; then
	    log_message ""
	    log_message "Error updating ${MODPROBE_CONF}"
	    log_message "${GENERIC_MESSAGE}"
	    exit 140
	fi
    else
	# Remove the unmodified temp file.
	rm -f ${MODPROBE_CONF_TEMP}
    fi

    return ${RETURN_VALUE}
}

# Function:  unconfigure_modprobe_conf()
#
# Description:
#   Remove any "install" line for the lpfcdfc module.
#
# Parameters:
#   A list of driver modules.
#
# Returns a bit pattern with the following values:
#   0 if the /etc/modprobe.conf file is not modified,
#   2 if the /etc/modprobe.conf file is modified with changes that do not require the initrd to be rebuilt.
unconfigure_modprobe_conf()
{
    local RETURN_VALUE
    let RETURN_VALUE=0

    log_message "Configuring ${MODPROBE_CONF} ..."
    backup_modprobe_conf ${MODPROBE_CONF_TEMP}

    # Remove the "install" line if necessary.
    if [ $(grep -c -e "^[[:space:]]*install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]\+/sbin/modprobe[[:space:]]\+${DRIVER_NAME}[[:space:]]\+\&\&[[:space:]]\+/sbin/modprobe[[:space:]]\+--ignore-install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]*\$" ${MODPROBE_CONF}) -ne 0 ] ; then
	grep -v -e "^[[:space:]]*install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]\+/sbin/modprobe[[:space:]]\+${DRIVER_NAME}[[:space:]]\+\&\&[[:space:]]\+/sbin/modprobe[[:space:]]\+--ignore-install[[:space:]]\+${DFCDRIVER_NAME}[[:space:]]*\$" ${MODPROBE_CONF_TEMP} > ${MODPROBE_CONF_TEMP2}
	mv -f ${MODPROBE_CONF_TEMP2} ${MODPROBE_CONF_TEMP}
	let RETURN_VALUE=$((${RETURN_VALUE}|2))
    fi

    if [ $((${RETURN_VALUE} & 3)) -ne 0 ] ; then
	if [ -e /etc/modprobe.elx ] ; then
	    mv -f ${MODPROBE_CONF_BACKUP} ${MODPROBE_CONF_BACKUP}.old
	fi
	cp -f ${MODPROBE_CONF} ${MODPROBE_CONF_BACKUP}
	if [ $? -ne 0 ] ; then
	    log_message ""
	    log_message "Error backing up ${MODPROBE_CONF}"
	    log_message "${GENERIC_MESSAGE}"
	    exit 130
	fi
	log_message "Original saved as ${MODPROBE_CONF_BACKUP}"
	mv -f ${MODPROBE_CONF_TEMP} ${MODPROBE_CONF}
	if [ $? -ne 0 ] ; then
	    log_message ""
	    log_message "Error updating ${MODPROBE_CONF}"
	    log_message "${GENERIC_MESSAGE}"
	    exit 140
	fi
    else
	rm -f ${MODPROBE_CONF_TEMP}
    fi

    return ${RETURN_VALUE}
}

# Function:  backup_files_to_elx()
#
# Description:
#   Copy each file passed as a parameter to filename.elx.
#
# Parameters:
#   A list of filenames to back up.
#
# Returns:
#   Nothing.
backup_files_to_elx()
{
    for i in $@ ; do
	cp -f $i $i.elx
	if [ $? -ne 0 ] ; then
	    log_message "Error $? copying $i to $i.elx"
	else
	    log_message "Original ramdisk image $i saved as $i.elx"
	fi
    done
}

# Function:  examine_build_configuration()
#
# Description:
#   Examines the system to verify that source package for the
#   currently running kernel and the gcc package are installed.
#
# Parameters:
#   none.
#
# Returns:
#   0 - The system is ready for installation of the LPFC driver.
#   1 - The kernel source needs to be installed.
#   2 - The gcc compiler package needs to be installed.
#   3 - Both the kernel source and gcc need to be installed.
#   4 - Kernel version could not be determined.
examine_build_configuration()
{
    local ERRORCONDITION
    local RETVAL
    let ERRORCONDITION=0

    if [ ${DISTRIBUTION} = "redhat" ] ; then
	log_message "Looking for kernel development package ..."
	KERNELDEVEL=$(rpm -qf ${KERNEL_IMAGE_PATH} --qf "%{NAME}-devel-%{VERSION}-%{RELEASE}\n")
	if [ $? -ne 0 ] ; then
	    let ERRORCONDITION=$((${ERRORCONDITION}|8))
	else
	    KERNELSOURCEVERSION=$(rpm -q ${KERNELDEVEL} 2>/dev/null)
	    if [ $? -ne 0 ]
		then
		let ERRORCONDITION=$((${ERRORCONDITION}|1))
	    fi
	fi
    else
	log_message "Looking for kernel source package ..."
	KERNELDEVEL=$(rpm -qf ${KERNEL_IMAGE_PATH} --qf "kernel-source-%{VERSION}-%{RELEASE}")
	if [ $? -ne 0 ] ; then
	    let ERRORCONDITION=$((${ERRORCONDITION}|8))
	else
	    KERNELSOURCEVERSION=$(rpm -q ${KERNELDEVEL} 2>/dev/null)
	    if [ $? -ne 0 ]
		then
		let ERRORCONDITION=$((${ERRORCONDITION}|1))
	    fi
	fi
    fi

    log_message "Looking for compilers ..."
    GCCVERSION=$(rpm -q --qf %{VERSION}-%{RELEASE} gcc)
    if [ $? -ne 0 ]
	then
	if [ ${ERRORCONDITION} -eq 0 ]
	    then
	    let ERRORCONDITION=$((${ERRORCONDITION}|2))
	else
	    let ERRORCONDITION=$((${ERRORCONDITION}|4))
	fi
    fi

    if [ $((${ERRORCONDITION}&1)) -ne 0 ] ; then
	log_message ""
	log_message "RPM cannot be installed: ${KERNELDEVEL} package is required."
	let NEED_SOURCE_PACKAGE=1
        return 1
    elif [ $((${ERRORCONDITION}&2)) -ne 0 ] ; then
	log_message ""
	log_message "RPM cannot be installed: gcc package is required."
	let NEED_GCC_PACKAGE=1
	return 2
    elif [ $((${ERRORCONDITION}&4)) -ne 0 ] ; then
	log_message "RPM cannot be installed ; kernel source and gcc packages are required."
	let NEED_SOURCE_PACKAGE=1
	let NEED_GCC_PACKAGE=1
	return 3
    elif [ $((${ERRORCONDITION}&8)) -ne 0 ] ; then
	log_message "RPM cannot be installed: kernel version could not be determined."
	return 4
    fi

    return 0
}

# Function:  install_rpm()
#
# Description:
#   Installed the specified RPM package.
#
# Parameters:
#   $1 - Package description.
#   $2 - Package Directory.
#   $3 - Package file name.
#   $4 - Package name.
#
# Returns:
#    0 - RPM successfully installed.
#    2 - A version of the package is already installed.
#    4 - An error occurred during RPM test.
#    5 - An error occurred during RPM installation.
#    6 - Could not find RPM file in specified path.
install_rpm()
{
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} $4 2>/dev/null)
    if [ $? -eq 0 ] ; then
	return 2
    fi
    log_message "Searching for $1 from $2 ..."
    if [ ! -e $2/$3 ] ; then
	log_message "Could not find $1 in path $2/$3!"
	return 6
    fi
    rpm -Uhv $2/$3 --test 2>/dev/null 1>/dev/null
    if [ $? -ne 0 ]; then
	log_message ""
	log_message "Error during RPM test"
	return 4
    else
	log_message "Installing package ..."
	exec_command "rpm -Uhv $2/$3 2>&1"
	if [ $? -ne 0 ]; then
	    log_message ""
	    log_message "Error during RPM installation"
	    return 5
	else
	    depmod -a
	    DRIVER_INSTALLED=1
	fi
    fi

    return 0
}

# Function:  load_driver()
#
# Description:
#   Load the specified driver.
#
# Parameters:
#   $1 - name of the driver to be loaded.
#   $2 - description of the driver to be loaded.
load_driver()
{
    log_message -en "Loading $2 ."
    exec_command "modprobe $1" background
    if [ $? -ne 0 ]; then
	log_message ""
	log_message "Error loading $2"
	log_message "Please refer to the following file(s) for more information"
	log_message "about this driver load failure:"
	for mesg in ${MESSAGESFILE} ; do
	    log_message -e "\t$mesg"
	done
	return 1
    fi
}

# Function:  install_dfcdriver_rpm()
#
# Description:
#   Install the ioctl driver RPM.
#
# Parameters:
#   $1 = 0  if driver is to be loaded after installation,
#   $1 != 0 if driver is not to be loaded after installation.
#
# Returns:
#    0 - RPM installed, or version of package currently installed
#         matches version of package to be installed.
#    1 - Error during RPM installation.
#    2 - Old package already installed.
#    3 - The current version of this package is already installed.
install_dfcdriver_rpm()
{
    install_rpm "${DFCDRIVER_DESCRIPTION}" "`pwd`/${DRIVER_DIR}" ${DFCDRIVER_RPM} ${DFCRPM_BASENAME}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -eq 2 ] ; then
	if [ ${INSTALLEDVERSION} = ${DFCDRIVER_VERSION} ] ; then
	    log_message "${DFCDRIVER_DESCRIPTION} version ${DFCDRIVER_VERSION} already installed."
	    return 3
	else
	    log_message "Another version of the ${DFCDRIVER_DESCRIPTION} is already installed."
	    log_message "Please execute this script with the '--uninstall' option to remove"
	    log_message "old versions of the Emulex Application Helper Module."
	    return 2
	fi
    elif [ ${RETURNVALUE} -ne 0 ] ; then
	log_message "Error installing LPFC Application Helper Module RPM."
	log_message "${GENERIC_MESSAGE}"
	return 1
    fi

    return 0
}

# Function:  load_dfcdriver_module
#
# Description:
#   Loads the lpfcdfc module.
#
# Parameters:
#   none.
#
# Returns:
#    0 - lpfcdfc module loaded.
#    1 - error loading lpfcdfc module.
load_dfcdriver_module()
{
    load_driver ${DFCDRIVER_NAME} "LPFC DFC Driver"
    if [ $? -ne 0 ] ; then
	log_message "${GENERIC_MESSAGE}"
	return 1
    fi

    return 0
}

# Function:  remove_rpm_package()
#
# Description:
#   Remove the specified RPM package if it is installed and if no
#   other packages depend on the virtual packages it provides.
#
# Returns:
#   0 - RPM removed.
#   1 - Error during RPM removal.
#   2 - Other packages depend on the package to be removed.
#   3 - RPM not installed.
remove_rpm_package()
{
    local retval=3

    while [ -n "$1" ]; do
	rpm -q $1 2>/dev/null 1>/dev/null
	if [ $? -eq 0 ] ; then
	    PACKAGES=$(rpm -q --whatrequires $1 2>&1)
	    if [ $? -ne 0 ] ; then
		log_message "Removing $2 ..."
		exec_command "rpm -e $1 2>&1"
		if [ $? -ne 0 ] ; then
		    log_message "An error occurred while uninstalling $1"
		    return 1
		else
		    let retval=0
		fi
	    else
		log_message "The following packages depend on $1:"
		log_message "${PACKAGES}"
		return 2
	    fi
	fi
	shift
	shift
    done

    return ${retval}
}

remove_file()
{
    if [ -e $1 ] ; then
	rm -f $1
	if [ $? -ne 0 ] ; then
	    log_message "An error occurred while removing $1"
	    return 1
	fi
    fi

    return 0
}

remove_dir()
{
    if [ -d $1 ] ; then
	rmdir $1
	if [ $? -ne -0 ] ; then
	    log_message "An error occurred while removing $1"
	    return 1
	fi
    fi

    return 0
}

# Function:  unload_driver()
#
# Description:
#   Unload the specified driver if it is loaded and unused.
#
# Parameters:
#   $1 - Name of module to be unloaded.
#
# Returns:
#   0 - module successfully unloaded
#   1 - an error occurred while unloading the module.
#   2 - module is being used and cannot be unloaded.
#   3 - module is being referenced by other modules and cannot be
#       unloaded.
#   4 - module was not loaded.
#   
unload_driver()
{
    LSMOD=$(lsmod | grep -e "^$1\?[[:space:]]\+[[:digit:]]\+[[:space:]]\+[[:digit:]]\+")
    if [ $? -ne 0 ] || [ -z "${LSMOD}" ] ; then
	return 4
    fi

    AWK_MODULE=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $1; }'`
    let AWK_USECOUNT=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $3; }'`
    AWK_REFERENCES=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $4; }'`

    if [ ${AWK_MODULE} != $1 ] ; then
	log_message "ERROR - module found is not the module we're looking for."
	log_message "AWK_MODULE=${AWK_MODULE}"
	log_message "MODULE=$1"
	exit 150
    fi

    if [ ${AWK_USECOUNT} -eq 0 ] ; then
	if [ -z ${AWK_REFERENCES} ] || [ ${AWK_REFERENCES} = "(unused)" ] ; then
	    rmmod $1
	    if [ $? -ne 0 ] ; then
		log_message "An error occurred while unloading $1"
		return 1
	    fi
	else
	    return 3
	fi
    else
	return 2
    fi

    return 0
}

initscript_install()
{
    log_message "Installing Emulex Application Helper Module startup script ..."
    cp ${INITSCRIPT_SOURCE} ${INITSCRIPT_DESTINATION}
    if [ $? -eq 0 ]; then
	if [ ${DISTRIBUTION} = redhat ] ; then
	    chkconfig --add ${INITSCRIPT_NAME} && \
		chkconfig --level 2345 ${INITSCRIPT_NAME} on
	else
	    chkconfig --add ${INITSCRIPT_NAME} && \
		chkconfig ${INITSCRIPT_NAME} on
	fi
	if [ $? -eq 0 ] ; then
	    DRIVER_INSTALLED=1
	else
	    log_message ""
	    log_message "Error installing elxlpfc startup script"
	    log_message "${GENERIC_MESSAGE}"
	    exit 97
	fi
    else
	log_message ""
	log_message "Error copying startup script to ${INITSCRIPT_DESTINATION}"
	log_message "${GENERIC_MESSAGE}"
	exit 95
    fi
}

initscript_uninstall()
{
    if [ -e ${INITSCRIPT_DESTINATION} ] ; then
	log_message "Removing Emulex Application Helper Module startup script ..."
	chkconfig --del ${INITSCRIPT_NAME}
	remove_file "${INITSCRIPT_DESTINATION}" || return 1
    fi

    return 0
}

print_help()
{
    log_message ""
    log_message "This script will by default install version ${DFCDRIVER_VERSION} of the"
    log_message "Emulex Linux Fibre Channel Application Helper Module.  The"
    log_message "following options may also be used:"
    log_message ""
    log_message "-h,--help            - Print this help message."
    log_message "-u,--uninstall       - Uninstall previously installed driver kit."
    log_message "-k,--upgradekernel   - Install a previously installed Application"
    log_message "                        Helper Module kit into an upgraded kernel."
}

uninstall_kit()
{
    let UNINSTALL_ERRORS=0
    let REBOOT_REQUIRED=0
    let NOREBOOT_REQUIRED=0
    let PACKAGE_REMOVED=0

    log_message "Checking for Emulex Application Helper Module packages ..."
    remove_rpm_package "${DFCRPM_BASENAME}" "LPFC Application Helper Module source RPM"
    case "$?" in
	0)  let PACKAGE_REMOVED=1 ;;
	1)  let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1
	    exit 10 ;;
	2)  log_message "Please remove the dependent packages and then"
	    log_message "run this script with the '--uninstall' option again."
	    exit 12 ;;
	3)  ;;
	*)  let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1
	    exit 10 ;;
    esac

    initscript_uninstall || let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1

    # Remove a bunch of files.
    if [ ${PACKAGE_REMOVED} -ne 0 ] ; then
	files=( "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfc/lpfcdfc.ko" \
	        "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfcdfc.ko")
	for i in ${files[@]} ; do
	    remove_file $i || let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1
	done
    fi

    # Unload a bunch of drivers.
    drivers=(${DFCDRIVER_NAME})
    for i in ${drivers[@]} ; do
	unload_driver ${i}
	case "$?" in
	    0|4) ;;
	    1)  log_message "An error occurred while unloading ${i}."
		let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	    2)  MESGS="${MESGS}\no The ${i} driver is being used and cannot be unloaded."
		let REBOOT_REQUIRED=${REBOOT_REQUIRED}+1 ;;
	    3)  MESGS="${MESGS}\no The ${i} driver is being referenced by other"
		MESGS="${MESGS}\n  modules and cannot be unloaded."
		let REBOOT_REQUIRED=${REBOOT_REQUIRED}+1 ;;
	    *)  log_message "An unknown error occurred while uninstalling ${i}."
		let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	esac
    done

    # Restore old application helper modules if necessary.
    restore_old_driver

    unconfigure_modprobe_conf

    # Check for any uninstall errors.
    local TOTAL_MESSAGES
    let TOTAL_MESSAGES=$((${REBOOT_REQUIRED}+${NOREBOOT_REQUIRED}))
    if [ ${UNINSTALL_ERRORS} -ne 0 ] ; then
	log_message ""
	log_message "Uninstallation of Emulex Application Helper Module was not successful."
	log_message ""${GENERIC_MESSAGE}""
	exit 10
    elif [ ${TOTAL_MESSAGES} -ne 0 ] ; then
	log_message -en "\n${TOTAL_MESSAGES} message"
	if [ ${TOTAL_MESSAGES} -ne 1 ] ; then
	    log_message -n "s"
	fi
	log_message -e " generated during uninstallation:\n${MESGS}\n"
	if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	    log_message "Please reboot this system to complete the uninstallation"
	    log_message "of the Emulex LPFC Application Helper Module kit."
	    exit 25
	fi
	exit 0
    else
	log_message "Uninstallation complete."
	exit 0
    fi
}

install_kit()
{
    check_for_driver_kit
    case "$?" in
	1)  exit 0  ;; # Application Helper Module already installed.
	2)  log_message
	    log_message "No lpfc.ko module is installed for this kernel.  Please"
	    log_message "install the ${LPFCDRIVER_VERSION} LPFC driver for this kernel or"
	    log_message "upgrade to a kernel that includes this version of the"
	    log_message "LPFC driver before proceeding with this installation."
	    exit 102 ;;
	3)  log_message
	    log_message "Multiple versions of ${DRIVER_NAME}.ko exist in /lib/modules/${UNAME}."
	    log_message "Please make sure that the ${LPFCDRIVER_VERSION} version of the LPFC driver"
            log_message "is the only version installed for this kernel."
	    exit 101 ;;
	4)  log_message
	    log_message "The ${DRIVER_NAME}.ko module in /lib/modules/${UNAME} is version ${LPFC_MODULEVERSION},"
	    log_message "but version ${LPFCDRIVER_VERSION} is required for installation of the Application"
	    log_message "Helper Module to proceed.  Please install the ${LPFCDRIVER_VERSION} LPFC driver kit"
	    log_message "or upgrade to a kernel that includes this version of the LPFC driver."
	    exit 103 ;;
	5)  log_message
	    log_message "Version ${INSTALLEDVERSION} of the ${INSTALLEDPACKAGE} RPM is installed."
	    log_message "Please remove this package and run this installation again."
	    exit 104 ;;
	6)  log_message
	    log_message "Error attempting to find the lpfcdfc.ko modules in /lib/modules/${UNAME}."
	    log_message "${GENERIC_MESSAGE}"
	    exit 105 ;;
	7)  log_message
	    log_message "The ${INSTALLEDPACKAGE} RPM needs to be repaired.  Please reinstall"
	    log_message "this RPM, or remove it and then run this installation script again."
	    exit 106 ;;
	8)  log_message
	    log_message "Multiple instances of the ${DFCDRIVER_NAME}.ko module exist in the "
	    log_message "/lib/modules/${UNAME} directory.  The '${INSTALLEDPACKAGE}' RPM"
	    log_message "needs to be repaired.  Please uninstall this package and then run"
	    log_message "this installation script again."
	    exit 107 ;;
	*)  ;;         # No issues, continue with installation.
    esac

    examine_build_configuration
    case "$?" in
	0)  ;;
	1)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate kernel development RPM and then re-run"
	    log_message "this installation script."
	    exit 60
	    ;;
	2)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate development environment and then re-run"
	    log_message "this installation script."
	    exit 70
	    ;;
	3)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate kernel development RPM and development"
	    log_message "environment and then re-run this installation script."
	    exit 75
	    ;;
	*)  log_message "${GENERIC_MESSAGE}"
	    exit 2    
	    ;;
    esac

    let DRIVER_UNLOADED=0
    let REBOOT_REQUIRED=0
    let NOREBOOT_REQUIRED=0
    unload_old_drivers
    case "$?" in
	0)
	    ;;
	1|3|5|7)
	    log_message ""
	    log_message "${GENERIC_MESSAGE}"
	    exit 127 ;;
	2|4|6)
	    MESGS="${MESGS}\no An old Emulex Linux LPFC Application Helper Module"
	    MESGS="${MESGS}\n   could not be unloaded prior to the installation of"
	    MESGS="${MESGS}\n   the new driver kit."
	    let REBOOT_REQUIRED=$((${REBOOT_REQUIRED}+1))
	    let DRIVER_UNLOADED=1
	    ;;
	*)
	    log_message ""
	    log_message "${GENERIC_MESSAGE}"
	    exit 127 ;;
    esac

    backup_old_driver

    configure_modprobe_conf
    install_dfcdriver_rpm
    let RETVAL=$?
    if [ ${RETVAL} -ne 0 ] && [ ${RETVAL} -ne 3 ] ; then
	exit 52
    fi

    if [ ${DRIVER_UNLOADED} -eq 0 ] ; then
	load_dfcdriver_module || {
	    exit 54
	}
    fi

    initscript_install || {
	log_message "${GENERIC_MESSAGE}"
	exit 90
    }

    log_message "Application Helper Module installation complete."

    # Installation complete.  Print reboot messages if necessary.
    local TOTAL_MESSAGES
    let TOTAL_MESSAGES=$((${REBOOT_REQUIRED}+${NOREBOOT_REQUIRED}))
    if [ ${TOTAL_MESSAGES} -ne 0 ] ; then
	log_message -en "\n${TOTAL_MESSAGES} message"
	if [ ${TOTAL_MESSAGES} -ne 1 ] ; then
	    log_message -n "s"
	fi
	log_message -e " generated during installation:\n${MESGS}"
	if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	    log_message -e "\nPlease reboot this system to complete the installation"
	fi
	log_message "of the Emulex LPFC driver kit."
    fi
    if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	exit 20
    else
	exit 0
    fi
}

# Function:  upgrade_kernel()
#
# Description:
#
# Parameters:
#
# Returns:
#    0 - Success.
#    1 - Error building the lpfcdfc module for this kernel.
#    3 - Error removing the errlog file.
upgrade_kernel()
{
    # Check to see what's already installed.
    check_for_driver_kit
    case "$?" in
	0)  log_message
	    log_message "Error - no Application Helper Module RPM is installed."
	    log_message "Please install the Emulex Applications kit."
	    exit 255 ;; # Error - no RPM installed.
	1)  log_message
	    log_message "The Application Helper Module is properly installed"
	    log_message "for this kernel and does not need to be rebuilt."
	    return 0 ;; # Everything is hunky-dory.
	2)  log_message
	    log_message "No lpfc.ko module is installed for this kernel.  Please"
	    log_message "install the ${LPFCDRIVER_VERSION} LPFC driver for this kernel or"
	    log_message "upgrade to a kernel that includes this version of the"
	    log_message "LPFC driver and then re-install this package with"
	    log_message "the '--kernelupgrade' option."
	    exit 102 ;; # Error - lpfc.ko module needs to be installed for this kernel.
	3)  log_message
	    log_message "Multiple versions of ${DRIVER_NAME}.ko exist in /lib/modules/${UNAME}."
	    log_message "Please make sure that the ${LPFCDRIVER_VERSION} version of the LPFC driver"
            log_message "is the only version installed for this kernel."
	    exit 101 ;; # Error - lpfc.ko install needs to be fixed for this kernel.
	4)  log_message
	    log_message "The ${DRIVER_NAME}.ko module in /lib/modules/${UNAME} is version ${LPFC_MODULEVERSION},"
	    log_message "but version ${LPFCDRIVER_VERSION} is required for installation of the Application"
	    log_message "Helper Module to proceed.  Please install the ${LPFCDRIVER_VERSION} LPFC driver kit"
	    log_message "or upgrade to a kernel that includes this version of the LPFC driver."
	    exit 103 ;; # Error - install correct lpfc.ko or replace this apps kit with correct version.
	5)  log_message
	    log_message "Version ${INSTALLEDVERSION} of the ${INSTALLEDPACKAGE} RPM is installed."
	    log_message "Please remove this package and run this installation without the"
	    log_message "'--upgradekernel' option."
	    exit 104 ;; # Error - incorrect version of lpfcdfc RPM installed.
	6)  log_message
	    log_message "Error attempting to find the lpfcdfc.ko modules in /lib/modules/${UNAME}."
	    log_message "${GENERIC_MESSAGE}"
            exit 105 ;; # Error - 'find lpfcdfc.ko' failed.  Bail.
	7)  ;;          # Let's rebuild us a kernel module!
	8)  log_message
	    log_message "Multiple instances of the ${DFCDRIVER_NAME}.ko module exist in the "
	    log_message "/lib/modules/${UNAME} directory.  The '${INSTALLEDPACKAGE}' RPM"
	    log_message "needs to be repaired.  Please uninstall this package and then run"
	    log_message "this installation script without the '--upgradekernel' option."
	    exit 107 ;; # Error - lpfcdfc.ko install needs to be fixed for this kernel.
    esac

    # Make sure the build environment is properly configured.
    examine_build_configuration
    case "$?" in
	0)  ;;
	1)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate kernel development RPM and then run"
	    log_message "this installation script with the '--upgradekernel' option."
	    exit 60
	    ;;
	2)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate development environment and then"
	    log_message "re-run this installation script with the '--upgradekernel' option."
	    exit 70
	    ;;
	3)  log_message ""
	    log_message "Unable to successfully build and load the Application Helper Module."
	    log_message "Please install the appropriate kernel development RPM and development"
	    log_message "environment, and then re-run this installation script with the"
	    log_message "'--upgradekernel' option."
	    exit 75
	    ;;
	*)  log_message "${GENERIC_MESSAGE}"
	    exit 2    
	    ;;
    esac

    # Get to the Application Helper Module installation directcory.
    pushd ${DFCDRIVER_DIR} 1>/dev/null 2>/dev/null

    # Clean, build and install the Application Helper Module for the
    # currently running kernel.
    log_message -n "Building the lpfcdfc module ."
    exec_command "make clean 2>&1 && make OS=${MAKEDISTRO} build install >> ${DFCDRIVER_DIR}/errlog 2>&1" background
    if [ $? -ne 0 ] ; then
	log_message ""
	log_message "Error building the lpfcdfc module for this kernel."
	log_message "Log is contained in ${DFCDRIVER_DIR}/errlog"
	return 1
    fi

    # Execute the following line only if the driver does not exist for
    # this kernel.
    if [ $(grep -c $(uname -r) installed_kernels) -eq 0 ] ; then
	log_message "Adding this kernel to the installed_kernels file ..."
	uname -r >> installed_kernels
    fi

    # Re-calculate the module dependencies for this kernel.
    depmod -a
    if [ $? -ne 0 ] ; then
	log_message ""
	log_message "Error recalculating module dependencies for"
	log_message "this kernel."
	return 2
    fi

    # No errors have occurred at this point, so it's safe to remove
    # the errlog file.
    rm -f ${DFCDRIVER_DIR}/errlog
    RETVAL=$?
    if [ ${RETVAL} -ne 0 ] ; then
	log_message "Error ${RETVAL} removing ${DFCDRIVER_DIR}/errlog"
	return 3
    fi

    # Go back from whence ye came.
    popd 1>/dev/null 2>/dev/null

    # Load the newly built lpfcdfc.ko module.
    load_dfcdriver_module || {
	exit 54
    }

    # And return with success.  Who needs error checking?
    return 0
}

# Initialize the log file.
log_message -init

log_message "Emulex LPFC Application Helper Module Installer Version ${INSTALLER_VERSION}"

# Process the parameters
SCRIPT_COMMAND="install"
while [ $# -ne 0 ] ; do
    case "$1" in
	-h|--help)
	    print_help
	    exit 0
	    ;;
	-k|--upgradekernel)
	    SCRIPT_COMMAND="upgradekernel"
	    ;;
	-u|--uninstall)
	    SCRIPT_COMMAND="uninstall"
	    ;;
	--)
	    break
	    ;;
	*)
	    log_message "Invalid option - $1"
	    SCRIPT_COMMAND="badoption"
	    ;;
    esac
    shift
done

# Exit if an invalid parameter was specified by the user.
if [ -n "${SCRIPT_COMMAND}" ] && [ ${SCRIPT_COMMAND} = "badoption" ] ; then
    log_message ${HELP_MESSAGE}
    exit 5
fi
    
log_message "Determining distribution type and kernel version ..."

if ! get_distribution; then
   log_message "${GENERIC_MESSAGE}"
   exit 1
fi

# cd to the package directory
cd ${0%/*}

if [ -z "${SCRIPT_COMMAND}" ] ; then
    log_message "Fatal error - SCRIPT_COMMAND has no value."
    exit 255
elif [ ${SCRIPT_COMMAND} = "uninstall" ] ; then
    uninstall_kit
elif [ ${SCRIPT_COMMAND} = "install" ] ; then
    install_kit
elif [ ${SCRIPT_COMMAND} = "upgradekernel" ] ; then
    upgrade_kernel
else
    log_message "Fatal error - invalid value for SCRIPT_COMMAND."
    exit 255
fi

exit 0
